package com.pan.mapping;

import com.pan.entity.PosNameMapper;
import com.pan.utils.ToStringUtils;

import java.lang.reflect.Field;
import java.util.*;
import java.util.function.Function;

public class LineToObject<T> {

    private Class<T> targetClass;
    private List<CellToField> ctfList;
    private int maxPos;

    /**
     *
      * @param targetClass 映射的类的Class
     * @param pnmList 主要用于设置映射关系
     */
    public LineToObject(Class<T> targetClass, List<PosNameMapper> pnmList){
        this.targetClass = targetClass;
        HashMap<String, Field> nameFieldMap = Arrays.stream(targetClass.getDeclaredFields())
                .collect(HashMap::new,
                        (hashMap,field) -> hashMap.put(field.getName(),field),
                        HashMap::putAll);
        HashSet<Integer> posSet = new HashSet<>();
        this.ctfList = new ArrayList<>();
        for (PosNameMapper pn : pnmList){
            if (!nameFieldMap.containsKey(pn.getName())) {
                throw new RuntimeException("属性名不存在");
            }
            Field field = nameFieldMap.get(pn.getName());
            this.ctfList.add(new CellToField<>(pn,field));

            if (posSet.contains(pn.getPosition())||pn.getPosition()<0) {
                throw new RuntimeException("位置错误");
            }
            posSet.add(pn.getPosition());
            if (maxPos < pn.getPosition()) {
                maxPos = pn.getPosition();
            }
        }
    }

    public void resetMapping(List<PosNameMapper> pnmList){
        HashMap<String, Field> nameFieldMap = Arrays.stream(targetClass.getDeclaredFields())
                .collect(HashMap::new,
                        (hashMap,field) -> hashMap.put(field.getName(),field),
                        HashMap::putAll);
        HashSet<Integer> posSet = new HashSet<>();
        this.ctfList = new ArrayList<>();
        for (PosNameMapper pn : pnmList){
            if (!nameFieldMap.containsKey(pn.getName())) {
                throw new RuntimeException("属性名不存在");
            }
            Field field = nameFieldMap.get(pn.getName());
            this.ctfList.add(new CellToField<>(pn,field));

            if (posSet.contains(pn.getPosition())||pn.getPosition()<0) {
                throw new RuntimeException("位置错误");
            }
            posSet.add(pn.getPosition());
            if (maxPos < pn.getPosition()) {
                maxPos = pn.getPosition();
            }
        }
    }



    public T arrToObject(String[] arr){
        if (arr.length>maxPos+1) {
            throw new RuntimeException("传入数组列数错误");
        }

        T target;
        try {
            target = targetClass.getDeclaredConstructor().newInstance();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        this.ctfList.stream()
                .forEach(cellToField -> {
                    String content = arr[cellToField.getPosNameMapper().getPosition()];
                    cellToField.fieldSet(target,
                                    content.length()==0?null:content);
                });
        return target;
    }

    public String[] objectToArr(T object){
        String[] arr = new String[maxPos + 1];
        for (int i=0;i<maxPos+1;i++) arr[i] = "";
        ctfList.forEach(cellToField -> {
            int position = cellToField.getPosNameMapper().getPosition();
            arr[position] = cellToField.fieldGetString(object);
        });
        return arr;
    }

}
